package com.example.demo.util;

import org.jtransforms.dct.DoubleDCT_2D;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.util.ArrayList;
import java.util.List;
import java.lang.String;

// PHash 算法实现类
class PHash {
    public static String pHash(BufferedImage image) {
        image = removeNoise(image);
        BufferedImage resizedImage = resize(image, 32, 32);
        BufferedImage grayImage = toGrayscale(resizedImage);
        double[][] dct = dct(convertToDoubleArray(grayImage));
        double[][] topLeft = extractTopLeft(dct, 8, 8);
        double average = calculateAverage(topLeft);
        return generateHash(topLeft, average);
    }

    // 去除噪声的方法
    private static BufferedImage removeNoise(BufferedImage image) {
        float[] blurMatrix = {
                1 / 9f, 1 / 9f, 1 / 9f,
                1 / 9f, 1 / 9f, 1 / 9f,
                1 / 9f, 1 / 9f, 1 / 9f
        };
        Kernel kernel = new Kernel(3, 3, blurMatrix);
        ConvolveOp convolveOp = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
        return convolveOp.filter(image, null);
    }

    private static BufferedImage resize(BufferedImage image, int width, int height) {
        BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = resizedImage.createGraphics();
        g2d.drawImage(image, 0, 0, width, height, null);
        g2d.dispose();
        return resizedImage;
    }

    private static BufferedImage toGrayscale(BufferedImage image) {
        BufferedImage grayImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
        Graphics2D g2d = grayImage.createGraphics();
        g2d.drawImage(image, 0, 0, null);
        g2d.dispose();
        return grayImage;
    }

    private static double[][] convertToDoubleArray(BufferedImage image) {
        int width = image.getWidth();
        int height = image.getHeight();
        double[][] array = new double[width][height];
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                Color color = new Color(image.getRGB(x, y));
                array[x][y] = color.getRed();
            }
        }
        return array;
    }

    private static double[][] dct(double[][] data) {
        int width = data.length;
        int height = data[0].length;
        double[][] result = new double[width][height];
        for (int u = 0; u < width; u++) {
            for (int v = 0; v < height; v++) {
                double sum = 0;
                for (int i = 0; i < width; i++) {
                    for (int j = 0; j < height; j++) {
                        sum += data[i][j] * Math.cos((2 * i + 1) * u * Math.PI / (2 * width)) * Math.cos((2 * j + 1) * v * Math.PI / (2 * height));
                    }
                }
                double cu = (u == 0) ? 1.0 / Math.sqrt(2) : 1;
                double cv = (v == 0) ? 1.0 / Math.sqrt(2) : 1;
                result[u][v] = 0.25 * cu * cv * sum;
            }
        }
        return result;
    }

//    // 二维离散余弦变换（DCT），使用 JTransforms 库
//    private static double[][] dct(double[][] data) {
//        int width = data.length;
//        int height = data[0].length;
//        DoubleDCT_2D dct = new DoubleDCT_2D(width, height);
//        double[][] result = new double[width][height];
//        for (int i = 0; i < width; i++) {
//            System.arraycopy(data[i], 0, result[i], 0, height);
//        }
//        dct.forward(result, false);
//        return result;
//    }

    private static double[][] extractTopLeft(double[][] data, int width, int height) {
        double[][] result = new double[width][height];
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                result[x][y] = data[x][y];
            }
        }
        return result;
    }

    private static double calculateAverage(double[][] data) {
        int width = data.length;
        int height = data[0].length;
        double sum = 0;
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                sum += data[x][y];
            }
        }
        return sum / (width * height);
    }

    private static String generateHash(double[][] data, double average) {
        int width = data.length;
        int height = data[0].length;
        StringBuilder hash = new StringBuilder();
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                if (data[x][y] > average) {
                    hash.append('1');
                } else {
                    hash.append('0');
                }
            }
        }
        return hash.toString();
    }
}

